package cn.ac.cintcm.prespring.cluster.base;

import java.util.HashSet;
import java.util.List;
import java.util.Set;


public class Similarity {
	public static float simRate = 0.6f;

	public float getSimRate() {
		return simRate;
	}

	public void setSimRate(float simRate1) {
		simRate = simRate1;
	}

	public Similarity() {
	}

	public Similarity(float simRate1) {
		simRate = simRate1;
	}

	public static boolean isSim(Set<Integer> a, Set<Integer> b) {
		if (a == null || b == null || a.size() == 0 || b.size() == 0) {
			return false;
		}
		int intersection = join(a, b);
		float rate = 2 * (float) intersection / (float) (a.size() + b.size());
		if (rate >= simRate) {
			return true;
		} else
			return false;
	}

	/**
	 * elements in a and b should be ordered from low to high
	 */
	public static boolean isSim(List<Integer> a, List<Integer> b) {
		if (a == null || b == null || a.size() == 0 || b.size() == 0) {
			return false;
		}
		int intersection = join(a, b);
		float rate = 2 * (float) intersection / (float) (a.size() + b.size());
		if (rate >= simRate) {
			return true;
		} else
			return false;
	}
	
	/**
	 * elements in a and b should be ordered from low to high
	 */
	public static float simRate(List<Integer> a, List<Integer> b){
		if (a == null || b == null || a.size() == 0 || b.size() == 0) {
			return 0f;
		}
		int intersection = join(a, b);
		float rate = 2 * (float) intersection / (float) (a.size() + b.size());
		return rate;
	}

	/**
	 * whether a and b are similar based on their Longest Common String length
	 */
	public static boolean isLCSsim(String a, String b) {
		//System.err.println("LCS");
		if (a == null || b == null || a.equals("") || b.equals("")) {
			return false;
		}
		int lcs = LCS.LCSlength(a, b);
		int longer = (a.length() >= b.length()) ? a.length() : b.length();
		float rate = (float) lcs / (float) longer;
		if (rate >= simRate) {
			return true;
		}
		return false;
	}
	
	/**
	 * similarity between a and b based on their Longest Common String length
	 */
	public static float LCSimRate(String a,String b){
		if (a == null || b == null || a.equals("") || b.equals("")) {
			return 0f;
		}
		int lcs = LCS.LCSlength(a, b);
		int longer = (a.length() >= b.length()) ? a.length() : b.length();
		float rate = (float) lcs / (float) longer;
		return rate;
	}
	
	/**
	 * whether a and b are similar based on their Edit Distance (Levenshtein Distance)
	 */
	public static boolean isLDsim(String a,String b){
		//System.err.println("Levenshtein Distance");
		if (a == null || b == null || a.equals("") || b.equals("")) {
			return false;
		}
		int ed=EditDistance.LD(a, b);
		int longer = (a.length() >= b.length()) ? a.length() : b.length();
		float rate = 1- (float) ed / (float) longer;
		if (rate >= simRate) {
			return true;
		}
		return false;
	}
	
	/**
	 * similarity between a and b based on their Edit Distance (Levenshtein Distance)
	 */
	public static float LDsimRate(String a,String b){
		if (a == null || b == null || a.equals("") || b.equals("")) {
			return 0f;
		}
		int ed=EditDistance.LD(a, b);
		int longer = (a.length() >= b.length()) ? a.length() : b.length();
		float rate = 1- (float) ed / (float) longer;
		return rate;
	}

	/**
	 * elements in a and b should be ordered from low to high
	 * 
	 * @return intersection size of a and b
	 */
	private static int join(List<Integer> a, List<Integer> b) {
		int intersection = 0;
		int aValue = a.get(0);
		int bValue = b.get(0);
		int ai = 0;
		int bj = 0;
		while (0 == 0) {
			if (aValue == bValue) {
				intersection++;
				ai++;
				bj++;
			} else if (aValue < bValue) {
				ai++;
			} else {
				bj++;
			}
			if (ai == a.size() || bj == b.size()) {
				break;
			}
			aValue = a.get(ai);
			bValue = b.get(bj);
		}
		return intersection;
	}

	private static int join(Set<Integer> a, Set<Integer> b) {
		Set<Integer> temp = new HashSet<Integer>();
		temp.addAll(a);
		temp.retainAll(b);
		int joinSize = temp.size();
		temp.clear();
		temp = null;
		return joinSize;
	}

}
